home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
-
- ;Usage is: call envsub ds:si -> length,string
-
- ; string is of form: name=value
-
- ;clone of SET command that demonstrates updating
- ; the environment string.
- ;If there is no secondary command processor, the
- ; global environment is updated
- ;If there is a secondary command processor, then
- ; its enviroment is updated
-
- sb segment at 0 ;equates storage blocks and psp's
-
- sb_kind db ' ' ;type of storage block: 'M' or 'Z'
- sb_psp dw ? ;psp segment address
- sb_length dw ? ;sb length in paragraphs
- sb_head_length equ 10h ;length of sb header
-
- org 0h ;program segement prefix equates
- psp_ret_int dw ? ;int 20h
- org 2Ch
- psp_env dw ? ;segment address of environment
- org 50h
- psp_dos_function dw ? ;address of function dispatcher
- org 80h
- psp_parm_string db ? ;1 byte length plus parm string
-
- psp_length equ 100h
-
- sb ends
-
- code_seg segment para public
- assume cs:code_seg,ds:code_seg,es:sb
- public env_set
-
- ;local data
-
- cr equ 13
- lf equ 10
-
- sb_count dw 0 ;count of sb's encountered
- sb_shell dw 0 ;segment address of shell sb
- sb_shell_env dw 0 ;segment address of global env sb
- sb_secondary dw 0 ;segment address of secondary command.com
- sb_secondary_env dw 0 ;segment address of secondary command env
-
- fatal_msg equ 80h
- error_msg equ 40h
- info_msg equ 20h
- msg_flag db fatal_msg+error_msg
-
- secondary_msg db info_msg,'Secondary '
- command_found db info_msg,'COMMAND.COM found',cr,lf,'$'
- bad_dos_msg db fatal_msg,'Must be running under DOS 2.0 or above',cr,lf,'$'
- bad_sb_msg db fatal_msg,'Bad storage block',cr,lf,'$'
- bad_env_msg db error_msg,'Bad environment block',cr,lf,'$'
- command_lost db error_msg,'Shell never found',cr,lf,'$'
- addbadmsg db error_msg,'Environment corrupt',cr,lf,'$'
- addmsg db info_msg,'Addition requested',cr,lf,'$'
- removemsg db info_msg,'Removal requested',cr,lf,'$'
- env_set_nospace db error_msg,'No space in environment string',cr,lf,'$'
- env_set_syntax db error_msg,'Set string syntax error',cr,lf,'$'
-
- type_string proc near ;type message at offset in dx
- push ax ;save registers
- push cx
- push dx
- push si
-
- mov si,dx ;get message level
- lodsb
- and al,msg_flag ;compare to what sells
- jz type_ret ;if not on list, send to bit bucket
-
- mov dx,si
- mov ax,0900h
- int 21h
- type_ret:
- pop si
- pop dx
- pop cx
- pop ax
- ret
- type_string endp
-
- get_first_sb proc near ;get first storage block, point es at it
- push ax
- push bx
- mov ax,5200h
- int 21h ;es:bx points to memory block anchor+2
- dec bx
- dec bx
- mov es,es:[bx] ;get first memory block address into es
- pop bx
- pop ax
- ret
- get_first_sb endp
-
- get_next_sb proc near
- push ax
- mov ax,es ;get current paragraph
- add ax,sb_length ;add in number of paragraphs
- inc ax ;add 1 for header
- mov es,ax ;set new extra segment address
- pop ax
- ret
- get_next_sb endp
-
-
- find_secondary_env proc near ;find env sb's for current program sb
- push ax ;pointed to by es
- push es
- mov ax,es ;get address of secondary cp's sb
- inc ax ;get its psp address
- find_secondary_env_loop:
- call get_next_sb ;get next sb
- cmp ax,sb_psp ;match secondary's psp?
- jne find_secondary_env_next ;if not, skip
-
- mov sb_secondary_env,es ;otherwise, save
- find_secondary_env_next:
- cmp sb_kind,'Z' ;last block?
- jne find_secondary_env_loop
-
- pop es
- pop ax
- ret
- find_secondary_env endp
-
- command_test proc near ;test program storage block at es:0
- push ax
- push bx
- push cx
- push dx
- push ds
- push es
- push si
-
- cmp sb_count,2
- ja command_second
-
- mov dx,offset command_found
- call type_string
- mov sb_shell,es
- jmp command_test_good
-
- command_second:
- cmp sb_shell,0 ;did we find shell?
- je command_first_bad ;if not, error
-
- cmp word ptr es:psp_env+sb_head_length,0 ;check environment of program
- je command_test_good ;if no environment, quit
-
- push sb_shell
- pop ds ;ds points to shell
- mov al,byte ptr es:sb_head_length+psp_length
- cmp al,0E9h ;a JMP?
- jne command_test_good ;if not, no harm done
-
- cmp al,byte ptr ds:sb_head_length+psp_length ;check 1st instruction
- jne command_first_bad
-
- mov si,sb_head_length+psp_length
- mov di,sb_head_length+psp_length
- mov cx,10 ;look at 10 words of code
- repz cmpsw
- clc
- jcxz command_test_found ;if they all match, fine
-
- jmp command_test_good ;if not, no harm done
-
- command_test_found:
- push cs
- pop ds
- mov sb_secondary,es
-
- mov ax,es:psp_env+sb_head_length ;get env address
- dec ax ;back up over sb header
- mov sb_secondary_env,ax ;and save it
-
- call find_secondary_env ;look for other env's
-
- mov dx,offset secondary_msg
- call type_string
- jmp command_test_good
-
- command_first_bad:
- mov dx,offset command_lost
- call type_string
- stc
- jmp command_test_end
-
- command_test_good:
- clc
- command_test_end:
- pop si
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
-
- ret
- command_test endp
-
-
-
- prog_test proc near ;test block for program
- push ax ;save registers
- push cx
- push dx
- push es
-
- mov ax,sb_psp ;get PSP of owner
- cmp ax,0 ;if zero, it is free
- je prog_exit
-
- cmp ax,8 ;if PSP of owner is at 8
- je prog_exit ;block owned by config.sys
-
- sub ax,sb_head_length ;get address of sb containg program
- cmp ax,sb_shell ;is owner the primary shell?
- je prog_exit
- push es
- pop ax
- cmp ax,sb_psp ;compare to address of owner
- ja prog_exit ;if owner below SB, system-owned
-
- add ax,sb_length ;add in length
- cmp ax,sb_psp ;compare to owner's PSP
- JB prog_exit ;if end below owner PSP, no program
- cmp sb_length,10 ;is block long enough to have a psp?
- jbe prog_exit ;if not, no program
-
- mov ax,word ptr es:psp_dos_function+sb_head_length
- cmp ax,word ptr cs:psp_dos_function ;check PSP validity
- jne prog_exit
-
- mov ax,word ptr es:psp_ret_int+sb_head_length
- cmp ax,word ptr cs:psp_ret_int ;check PSP validity
- jne prog_exit ;if invalid, skip looking for env
-
- call command_test
- clc
- prog_exit:
-
- pop es ;restore registers
- pop dx
- pop cx
- pop ax
- ret
-
- prog_test endp
-
- sb_scan proc near ;loop cx storage blocks
-
- mov al,sb_kind ;get storage block type byte
- cmp al,04dh ;ordinary storage block
- je sb_scan_got
- cmp al,05ah
- jne sb_scan_bad
- mov cx,1 ;last block
-
- sb_scan_got:
- inc sb_count ;count storage blocks
-
- cmp sb_count,3
- jne sb_scan_not_global
-
- mov sb_shell_env,es
- jmp sb_scan_get
-
- sb_scan_not_global:
- call prog_test ;look for program
-
- loop sb_scan_get
- jmp sb_scan_end
-
- sb_scan_get:
- call get_next_sb
- jmp sb_scan
-
- sb_scan_end:
- clc
- jmp sb_scan_exit
-
- sb_scan_bad:
- mov al,2
- mov dx,offset bad_sb_msg
- stc
-
- sb_scan_exit:
- ret
- sb_scan endp
-
-
- sb_anal proc near ;proc to analyze storage blocks
-
- push cx
- push dx ;carry flag = error
- push es ;error level in al
- mov ah,30h ;get release number
- int 21h
- cmp al,01h ;above dos 1.x?
- jna sb_bad_dos
-
- cld ;clear direction flag
- call get_first_sb
- mov cx,9999 ;scan all blocks
- call sb_scan
- jc sb_send_msg ;if any errors, exit
-
- jmp sb_exit
-
- sb_bad_dos:
- mov al,1
- mov dx,offset bad_dos_msg
- stc
- jmp sb_send_msg
-
- sb_bad_env:
- mov al,3
- mov dx,offset bad_env_msg
- stc
- sb_send_msg:
- pushf
- call type_string
- popf
- sb_exit:
- pop es
- pop dx
- pop cx
-
- ret
- sb_anal endp
-
- make_upper proc near ;make cx bytes at es:di upper case
-
- push ax ;save registers modified
- push cx
- push di
- push ds
- push si
-
- push es
- pop ds
- mov si,di
- make_upper_loop:
- lodsb ;get a byte
- cmp al,'a' ;if lower case:
- jb make_upper_next
- cmp al,'z'
- ja make_upper_next
- and al,255-'a'+'A' ;make upper case
- make_upper_next:
- stosb ;store out results
- loop make_upper_loop
-
- pop si ;restore registers
- pop ds
- pop di
- pop cx
- pop ax
- ret
- make_upper endp
-
-
-
- env_var_name proc near ;find environment variable name at
- push ax ; ds:si, length in cx
- push bx ;at exit, ds:di points to name
- push di ; name length in cx
- push es ;variable contents length to dx
-
- push cx ;save length and pointer
- push si ;for error exits
-
- jcxz env_var_name_bad ;if length is 0, exit
-
-
- push cs ;scan works at es:di
- pop es
- mov di,si
- mov al,' ' ;scan for non-blank
-
- env_var_strip:
- repz scasb ;look for non-blank
- jcxz env_var_name_bad ;if all blank, error!
-
- inc cx ;back up over non-blank character
- dec di
- mov si,di ;save start of non-blank string
- mov bx,cx ;save length
-
- repnz scasb ;look for a blank
- mov dx,di ;save location of ' ' or end
-
- mov cx,bx ;reset search length
- mov di,si ;reset search pointer
- mov al,'=' ;search for equals sign
- repnz scasb
- jne env_var_name_bad ;if not found, error
-
- cmp di,dx ;compare location of '=' and ' '
- ja env_var_name_bad ;found ' ' first? then exit
-
- mov dx,bx ;restore search length
- add dx,si ;add start
- sub dx,di ;subtract where '=' was
-
- pop ax ;pop old si from stack
- pop ax ;pop old cx from stack
-
- mov cx,di ;where we found '='
- sub cx,si ;subtract string start
- dec cx ;minus 1 for '='
- clc ;all is well
- jmp env_var_name_exit
-
- env_var_name_bad:
- pop si ;restore pointer and length
- pop cx
- xor dx,dx ;contents length assumed zero
- stc ;problems - set carry
-
- env_var_name_exit:
- pop es
- pop di
- pop bx ;restore registers
- pop ax
- ret
-
- env_var_name endp
-
- get_sb_size proc near ;get byte size of sb at es:0 in cx
- push ax
- mov ax,sb_length ;get length of env in paragraphs
- mov cl,4 ;times 16
- shl ax,cl
- mov cx,ax
- pop ax
- ret
- get_sb_size endp
-
- env_var_find proc near ;find environment variable
- ;named in ds:si,name length in cx
- ;return string start in es:di
- ;length of entire string in cx
- push ax ;save registers
- push bx
- push dx
-
- mov bx,cx ;save length of name
- push es ;save env block address
- push ds ;set es:di to source string
- pop es ; "
- mov di,si ;make name upper case
- call make_upper ;altering input string
- pop es ;restore es to environment block
-
- call get_sb_size ;get size of sb in bytes
-
- mov di,sb_head_length ;start at data portion of block
- mov dx,cx ;save block length
-
- env_var_find_loop:
- push si ;save string pointers
- push di
-
- mov cx,bx ;compare for length of name
- mov ah,1 ;say not compare
- repz cmpsb ;compare item to name for name length
- jne env_var_find_next ;if not found, scan on
-
- cmp byte ptr es:[di],'=' ;check next byte for '='
- jne env_var_find_next ;if found, go calc length
-
- mov ah,0 ;say compare ok
- env_var_find_next:
- pop di ;restore string pointers
- pop si
-
- xor al,al ;look for end of current substring
- mov cx,dx ;search remainder of string
- mov dx,di ;save search start
- repnz scasb ;search for a zero
- jne env_var_find_end ;none found, error
-
- cmp ah,0 ;did original compare fly?
- je env_var_find_found;if so, then pass length, etc
-
- cmp byte ptr es:[di],0 ;check next byte for zero
- je env_var_find_end ;if found, name not found
-
- mov dx,cx ;save length of string remaining
- jmp env_var_find_loop ;and loop on
-
- env_var_find_end:
- xor cx,cx ;length = 0, none found
- stc ;set error flag
- jmp env_var_find_exit
-
- env_var_find_found:
- mov cx,di ;save count of end of string
- mov di,dx ;restore search start
- sub cx,di ;calc length of search
- dec cx ;less length of zero
- clc ;no errors
-
- env_var_find_exit:
- pop dx
- pop bx ;restore registers
- pop ax
- ret
- env_var_find endp
-
-
- null_var dw -1
-
- env_var_add proc near ;add environment variable
- ;expression ->ds:si, length in cx
- push ax ;save registers
- push bx
- push dx
-
- mov dx,offset addmsg
- call type_string
- mov bx,cx
- push si
- mov si,offset null_var ;send on wild goose chase
- mov cx,2 ;looking for x'ffff'
- call env_var_find ;es:di points to end of env
- pop si
- jnc env_var_add_env_bad
- ;es:di now points to end of env
- call get_sb_size ;get length of env area in cx
- add cx,sb_head_length ;add head length for offsets
- sub cx,bx ;deduct length of string
- sub cx,2 ;deduct length of flag
- cmp di,cx ;compare to where we add
- ja env_var_add_bad ;if no space, too bad
-
- mov cx,bx ;length of string to add
- rep movsb ;do the deed
- xor ax,ax ;make flag of two zeros
- stosw ;add is on
-
- jmp env_var_add_good
-
- env_var_add_env_bad:
- mov dx,offset addbadmsg
- call type_string
-
- env_var_add_bad:
- stc
- jmp env_var_add_exit
-
- env_var_add_good:
- clc
- env_var_add_exit:
- pop dx ;restore registers
- pop bx
- pop ax
- ret
-
- env_var_add endp
-
-
- env_var_remove proc near ;remove environment variable
- ;at es:di, length in cx
- push cx
- push dx
- push ds
- push di
- push si
-
- cld ;move left to right
-
- mov dx,offset removemsg
- call type_string
-
- inc cx ;add 1 for zero byte
- mov dx,cx ;save length of var
- call get_sb_size ;cx gets length of env area
- add cx,sb_head_length ;add header length for offsets
- sub cx,di ;deduct where we start
- sub cx,dx ;deduct length of removed variable
-
- mov si,di ;move from next variable
- add si,dx ;add my length
-
- push es ;do all the work in es:
- pop ds
-
- rep movsb ;do the move
-
- pop si
- pop di
- pop ds
- pop dx
- pop cx
- ret
- env_var_remove endp
-
-
- env_set proc near ;change environment per ds:si
- push ax
- push bx ;ds:si points to:
- push cx ; length db ?
- push di
- push ds ; data db 'name=value'
- push es
- push si
-
- xor ax,ax ;set length of local set string
- lodsb ;get length, push di forward
- mov cx,ax ;length of set string in cx
- call sb_anal ;analyze the storage block chain
- ;to find command processor(s)
- cmp sb_secondary_env,0 ;is there a secondary command proc?
- je env_set_shell ;if not, use primary
-
- mov es,sb_secondary_env ;command processor is secondary
- jmp env_set_command
-
- env_set_shell: ;command processor is shell
- mov es,sb_shell_env
- env_set_command:
- call env_var_name ;find what we want set at call
- ;ds:si -> expression, cx has length
- ;at return ds:si -> name
- ;cx is length of name
- jc env_set_syntax_err ;if not found, error
-
- mov bx,cx ;calculate new length of set string
- inc bx ;add 1 for '='
- add bx,dx ;add length of set string
-
- call env_var_find ;find variable in environment block
- ;at return, es:di -> start of env str
- ;cx is length of env str
- jc env_set_add ;if not found, just add
-
- call env_var_remove ;remove variable at es:di from env
- cmp dx,0 ;check out length of data to add
- je env_set_exit ;if zero, just exit
-
- env_set_add:
- mov cx,bx ;restore length of variable
- call env_var_add ;add new variable to set string
- jc env_set_no_space
- jmp env_set_exit
-
- env_set_no_space:
- mov dx,offset env_set_nospace
- jmp env_set_type
-
- env_set_syntax_err:
- mov dx,offset env_set_syntax
- env_set_type:
- call type_string
- env_set_error:
- stc
- env_set_exit:
- pop si
- pop es
- pop ds
- pop di
- pop cx
- pop bx
- pop ax
- ret
- env_set endp
-
- code_seg ends
- end
-